﻿/*
 * Jonathan
 * Created by: Jonathan Montiverdi
 * Date: 6/13/2012
 * License: http://jonathan.codeplex.com/license
 */
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;

using Jonathan.DataAccess;
using Jonathan.DataAccess.Sqlite;
using Jonathan.Logic;
using Monti.MVVM.Services;

namespace Jonathan.Data
{
   /// <summary>
   /// Description of Options.
   /// </summary>
   public class Options : IOptions
   {
      #region Fields
      
      private IMain m_Main;
      
      /// <summary>
      /// Event used to notify when the books have been refreshed.
      /// </summary>
      public event EventHandler BooksRefreshed;
      
      #endregion
      
      #region Setup
      
      /// <summary>
      /// Intializes a new options object.
      /// </summary>
      public Options ()
      {
         this.Books = new ObservableCollection <Book> ();
         this.AvailableBooks = new ObservableCollection <Book> ();
         this.Main.Disposing += this.Dispose;
      }
      
      #endregion
      
      #region Properties
      
      /// <summary>
      /// Gets the main application interface.
      /// </summary>
      [SqliteIgnore]
      public IMain Main { get { return this.m_Main ?? (this.m_Main = ServiceManager.Resolve <IMain> ()); } }

      /// <summary>
      /// Gets the list of available books.
      /// </summary>
      public ObservableCollection <Book> Books { get; private set; }

      /// <summary>
      /// Gets the list of available books.
      /// </summary>
      [SqliteIgnore]
      public ObservableCollection <Book> AvailableBooks { get; private set; }
      
      /// <summary>
      /// Gets or Sets the user preferences.
      /// </summary>
      public UserPreferences Configuration { get; set; }
      
      /// <summary>
      /// Gets the path to the options file.
      /// </summary>
      private string OptionsPath
      {
         get
         {
            string path;
            var savePerUser = RegistryData.GetSavePerUser ();
            if (savePerUser)
            {
               // TODO: Test this out...
               path = Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
               path += "\\SeekDeepWithin\\";
               if (!Directory.Exists (path)) Directory.CreateDirectory (path);
               path += "Jonathan\\";
               if (!Directory.Exists (path)) Directory.CreateDirectory (path);
               path += Common.OPTIONS_FILE;
            }
            else
               path = Common.DATA_DIR + Common.OPTIONS_FILE;
            
            return path;
         }
      }
      
      #endregion
      
      #region Methods
      
      /// <summary>
      /// Loads the options file.
      /// </summary>
      public void Load ()
      {
         var optionsPath = this.OptionsPath;
         if (File.Exists (optionsPath))
         {
            bool needsSaving = false;
            Sqlite.ReadAll (optionsPath, this);
            for (int a = this.Books.Count - 1; a >= 0; a--)
            {
               if (!this.Books[a].FileExists)
               {
                  this.Books.RemoveAt (a);
                  needsSaving = true;
               }
            }
            if (needsSaving)
               this.Save ();
         }
         else
            this.Configuration = new UserPreferences ();
      }
      
      /// <summary>
      /// Saves the options file.
      /// </summary>
      public void Save ()
      {
         Sqlite.Write (this.OptionsPath, this);
      }

      /// <summary>
      /// Loads a list of the books from the main database.
      /// </summary>
      public void LoadBooksFromMainDb ()
      {
         this.AvailableBooks.Clear ();
         if (File.Exists (Common.MAIN_DB_PATH))
         {
            Sqlite.Read (Common.MAIN_DB_PATH, this.AvailableBooks, "ORDER BY Name");
            if (!this.Books.Any (book => book.FileExists))
               this.Main.ShowLibrary ();
            this.Save ();
         }
      }
      
      /// <summary>
      /// Refreshes the list of books.
      /// </summary>
      public void RefreshBooks ()
      {
         if (this.BooksRefreshed != null)
            this.BooksRefreshed (this, EventArgs.Empty);
      }
      
      /// <summary>
      /// Releases any resourses and saves the options.
      /// </summary>
      /// <param name="sender">IMain.</param>
      /// <param name="e">EventArgs</param>
      public void Dispose (object sender, EventArgs e)
      {
         this.Main.Disposing -= this.Dispose;
         this.Save ();
      }
      
      #endregion
   }
}
